﻿using Autofac.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace PlutoStudio.Dependency
{
    /// <summary>
    /// Define interface for classes those are used to register dependencies.
    /// </summary>
    public interface IIocRegistrar
    {

        /// <summary>
        /// Adds a dependency registrar for conventional registration.
        /// </summary>
        /// <param name="registrar">dependency registrar</param>
        void AddConventionalRegistrar(IConventionalDependencyRegistrar registrar);

        /// <summary>
        /// Registers types of given assembly by all conventional registrars. See <see cref="IIocManager.IocContainer"/> method.
        /// </summary>
        /// <param name="assembly">Assembly to register</param>
        void RegisterAssemblyByConvention(Assembly assembly);
        /// <summary>
        /// Registers types of given assembly by all conventional registrars. See <see cref="IIocManager.IocContainer"/> method.
        /// </summary>
        /// <param name="assembly">Assembly to register</param>
        /// <param name="config"></param>
        void RegisterAssemblyByConvention(Assembly assembly, ConventionalRegistrationConfig config);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="module"></param>
        void RegisterModule(IModule module);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="installer"></param>
        void Install(IIocInstaller installer);

        /// <summary>
        /// Registers a type as self registration.
        /// </summary>
        /// <typeparam name="T">Type of the class</typeparam>
        /// <param name="lifeStyle">Lifestyle of the objects of this type</param>
        void Register<T>(LifetimeScopeStyle lifeStyle = LifetimeScopeStyle.Singleton)
            where T : class;

        /// <summary>
        /// Registers a type as self registration.
        /// </summary>
        /// <param name="type">Type of the class</param>
        /// <param name="lifeStyle">Lifestyle of the objects of this type</param>
        void Register(Type type, LifetimeScopeStyle lifeStyle = LifetimeScopeStyle.Singleton);

        /// <summary>
        /// Registers a type with it's implementation.
        /// </summary>
        /// <typeparam name="TType">Registering type</typeparam>
        /// <typeparam name="TImpl">The type that implements <see cref="TType"/></typeparam>
        /// <param name="lifeStyle">Lifestyle of the objects of this type</param>
        void Register<TType, TImpl>(LifetimeScopeStyle lifeStyle = LifetimeScopeStyle.Singleton) where TType : class where TImpl : class, TType;

        /// <summary>
        /// Registers a type with it's implementation.
        /// </summary>
        /// <param name="type">Type of the class</param>
        /// <param name="impl">The type that implements <paramref name="type"/></param>
        /// <param name="lifeStyle">Lifestyle of the objects of this type</param>
        void Register(Type type, Type impl, LifetimeScopeStyle lifeStyle = LifetimeScopeStyle.Singleton);
        /// <summary>
        /// Registers a type with it's implementation.
        /// </summary>
        /// <param name="type">Type of the class</param>
        /// <param name="impl">The type that implements <paramref name="type"/></param>
        /// <param name="lifeStyle">Lifestyle of the objects of this type</param>
        void RegisterGeneric(Type type, Type impl, LifetimeScopeStyle lifeStyle = LifetimeScopeStyle.Singleton);

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TType"></typeparam>
        /// <typeparam name="TImpl"></typeparam>
        /// <param name="component"></param>
        void Register<TType, TImpl>(TImpl component, bool injectProperties = true) where TType : class where TImpl : class, TType;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        /// <param name="component"></param>
        void Register<TComponent>(Type type, TComponent component, bool injectProperties = true) where TComponent : class;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="component"></param>
        void Register<TComponent>(TComponent component, bool injectProperties = true) where TComponent : class;

        /// <summary>
        /// Checks whether given type is registered before.
        /// </summary>
        /// <param name="type">Type to check</param>
        bool IsRegistered(Type type);

        /// <summary>
        /// Checks whether given type is registered before.
        /// </summary>
        /// <typeparam name="TType">Type to check</typeparam>
        bool IsRegistered<TType>();
    }
}
